package com.apes.fn.scm.settleCheck.model;


import com.apes.fn.scm.merchant.settlement.service.FeeRateService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;

import java.util.*;
import java.util.stream.Collectors;

import static com.apes.framework.api.SpringManager.getBean;


public class PartnerCheckCreate {

    // 缓存数据
    static List<PartnerCheck> cachePartnerCheck = new ArrayList<PartnerCheck>();

    static public void clearCache() {
        cachePartnerCheck.clear();
    }

    // 是否开启缓存
    static public boolean isCached = false;

    public enum Type {
        Supply("A10", "供应链管理费"),
        Platform("A01", "平台管理费-销售"),
        PlatformReduced("A02", "平台管理费-销售(减免)"),
        BasePlatform("A03", "平台管理费-定损基地"),
        InternalReduced("Internal", "内部销售(减免)"),
        UsedCar("B05", "二手车交易管理费"),
        T_MALL("T_MALL", "天猫平台费"),
        CXY("CXY", "车行易平台佣金");

        private final String id;
        private final String name;

        Type(String id, String name) {
            this.id = id;
            this.name = name;
        }
    }

    /***
     * 获取平台管理费(销售)
     */
    public void getPlatformManagementFee(Voucher voucher) {
        // 销售净额 = 总计 - 折扣
        getFee(accCost(voucher), Type.Platform);
    }

    /***
     * 获取平台管理费(减免)
     */
    public void getPlatformServiceFeeReduced(Voucher voucher) {
        // 销售净额 = 总计 - 折扣
        getFee(accCost(voucher), Type.PlatformReduced);
    }
    /***
     * 获取平台管理费(委托定损基地)
     */
    public void getBasePlatformServiceFee(Voucher voucher ,Type type) {
        if ("09".equals(voucher.getClassification()) && "RO003".equals(voucher.getScene().getId())) {
            // 委托定损返还 = 成本+ 定损信息费合计
            getFee(voucher.getVoucherItems().stream()
                    .filter(voucherItem -> voucherItem.getPriceTotal() - voucherItem.getDiscount() != 0)
                    .map(voucherItem -> MapUtil.mapper(
                            "voucherItem", voucherItem,
                            "product", voucherItem.getProduct(),
                            "classifyId", voucherItem.getProduct().getClassify().getId(),
                            "companyId", voucherItem.getVoucher().getCompany().getId(),
                            "cost", (voucherItem.getTaxCostPrice() * voucherItem.getProductQty()) + voucherItem.getLossQuotationFee()
                    ))
                    .filter(map -> (Double) map.get("cost") != 0)
                    .collect(Collectors.toList()), type);
        }

    }

    /***
     * 获取内部销售管理费(减免)
     */
    public void getPlatformInternalReduced(Voucher voucher) {
        // 销售净额 = 总计 - 折扣
        getFee(accCost(voucher), Type.InternalReduced);
    }

    private List<Map> accCost(Voucher voucher) {
        return voucher.getVoucherItems().stream()
                .filter(voucherItem -> voucherItem.getPriceTotal() - voucherItem.getDiscount() != 0)
                .map(voucherItem -> MapUtil.mapper(
                        "voucherItem", voucherItem,
                        "product", voucherItem.getProduct(),
                        "classifyId", voucherItem.getProduct().getClassify().getId(),
                        "companyId", voucherItem.getVoucher().getCompany().getId(),
                        "cost", voucherItem.getPriceTotal() - voucherItem.getDiscount()
                ))
                .filter(map -> (Double) map.get("cost") != 0)
                .collect(Collectors.toList());
    }

    /***
     * 获取供应链管理费(成本)
     */
    public void getSupplyChainManagementFee(Voucher voucher) {
        // 获取实际批次含税成本
        List<Map> calculateList = filterVoucherItem(voucher);

        getFee(calculateList, Type.Supply);
    }

    /***
     * 筛选需要计算供应链管理费的行
     * 1. 批次供应商如果是内部公司，且不等于A1001时，不计算“供应链管理费”
     * 2. 批次供应商可能既存在内部的也存在外部的
     * 3. 通过是否存在系统内部的公司来判断是内部供应商还是外部供应商
     */
    private List<Map> filterVoucherItem(Voucher voucher) {
        List<Map> result = new ArrayList<>();
        voucher.getVoucherItems().forEach(voucherItem -> getBean(VoucherInventoryRepository.class)
                .findAll(JpaDsl.toCriteriaByEq("voucherItem.id", voucherItem.getId()))
                .stream()
                .filter(voucherInventory -> {
                    if ("A1001".equals(voucherInventory.getInventorySupplier().getId())) {
                        return true;
                    }

                    PartyRole company = getBean(PartyRoleRepository.class).findByPartyIdAndRoleId(voucherInventory.getInventorySupplier().getParty().getId(), "Company");
                    // 无公司角色为外部供应商
                    return company == null;
                })
                .collect(Collectors.groupingBy(voucherInventory -> voucherInventory.getInventoryBatch().getSupplier().getId())).forEach((key, value) -> {
                    Double cost = value.stream().map(voucherInventory -> voucherInventory.getTaxCostPrice() * voucherInventory.getProductQty()).reduce(Arith::add).orElse(0.0);
                    if (cost != 0) {
                        result.add(MapUtil.mapper(
                                "voucherItem", voucherItem,
                                "product", voucherItem.getProduct(),
                                "classifyId", voucherItem.getProduct().getClassify().getId(),
                                "companyId", voucherItem.getVoucher().getCompany().getId(),
                                "supplierId", key,
                                "cost", cost));
                    }
        }));

        return result;
    }


    /***
     * 获取对应类型的费用
     */
    public void getFee(List<Map> calculteList, Type type) {
        if (calculteList.size() == 0) return;
        calculteList.forEach(
                item -> {
                    // 实际税率
                    double realRate = getFeeRate((String) item.get("companyId"), (String) item.get("classifyId"), type, item.containsKey("supplierId") ? (String) item.get("supplierId") : null);
                    double fee = (((Double) item.get("cost")) * realRate);

                    // 保留二位有效小数
                    fee = Arith.round(fee, 2);

                    if (type.id.equals(Type.Supply.id)) {
                        if (item.get("voucherItem") instanceof VoucherItem) {
                            ((VoucherItem) item.get("voucherItem")).setSupplyChainManagementFee(fee);
                        } else {
                            item.put("supplyChainManagementFee", fee);
                        }
                    } else {
                        if (type.id.equals(Type.Platform.id)) {
                            if (item.get("voucherItem") instanceof VoucherItem) {
                                ((VoucherItem) item.get("voucherItem")).setPlatformManagementFee(fee);
                            } else {
                                item.put("platformManagementFee", fee);
                            }
                        } else if (type.id.equals(Type.PlatformReduced.id)) {
                            if (item.get("voucherItem") instanceof VoucherItem) {
                                ((VoucherItem) item.get("voucherItem")).setPlatformServiceFeeReduced(fee);
                            } else {
                                item.put("platformManagementFee", fee);
                            }
                        }else if (type.id.equals(Type.BasePlatform.id)) {
                            if (item.get("voucherItem") instanceof VoucherItem) {
                                ((VoucherItem) item.get("voucherItem")).setBasePlatformManagementFee(fee);
                            } else {
                                item.put("platformManagementFee", fee);
                            }
                        }else if (type.id.equals(Type.UsedCar.id)) {
                            item.put("platformManagementFee", fee);
                        }
//                        else {
//                            if (item.get("voucherItem") instanceof VoucherItem) {
//                                ((VoucherItem) item.get("voucherItem")).setPlatformInternalReduced(fee);
//                            } else {
//                                item.put("platformManagementFee", fee);
//                            }
//                        }

                    }
                });
    }

    /**
     * 获取实际费率
     *
     * @param companyId
     * @param classifyId
     * @param type
     * @return
     */
    public double getFeeRate(String companyId, String classifyId, Type type,String supplierId) {
        if (type.id.equals(Type.Supply.id)) {
            return getBean(FeeRateService.class).getSupplyChainManagementFee(companyId, classifyId, supplierId);
        }
        if (type.id.equals(Type.Platform.id)) {
            return getBean(FeeRateService.class).getPlatformRules(companyId, new Date());
        }
        if (type.id.equals(Type.InternalReduced.id)) {
            return getBean(FeeRateService.class).getPlatformRules(companyId, new Date());
        }
        if (type.id.equals(Type.PlatformReduced.id)) {
            return getBean(FeeRateService.class).getPlatformReducedRules(companyId,classifyId, new Date());
        }
        if (type.id.equals(Type.BasePlatform.id)) {
            return getBean(FeeRateService.class).getPlatformRules(companyId, new Date());
        }
        if (type.id.equals(Type.UsedCar.id)) {
            return getBean(FeeRateService.class).getUsedCarPlatformRules(companyId);
        }
        if (type.id.equals(Type.T_MALL.id)) {
            return getBean(FeeRateService.class).getTmallPlatformRules(companyId);
        }
        if (type.id.equals(Type.CXY.id)) {
            return getBean(FeeRateService.class).getCXYRules(companyId);
        }
        return 0;
    }
}
